﻿using System.Collections.Generic;
using System.Linq;
using JetBrains.DocumentModel;
using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure;
using JetBrains.ReSharper.Feature.Services.CSharp.CodeCompletion.Infrastructure;
using JetBrains.ReSharper.Feature.Services.Lookup;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.CSharp.Util;
using JetBrains.ReSharper.Psi.Services;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.Util;

namespace MugenMvvmToolkit.ReSharper.ViewModels.CodeCompletions
{
    [Language(typeof(CSharpLanguage))]
    public class ValidatableViewModelValidateCodeCompletion :
        ItemsProviderOfSpecificContextWithSharedData
            <CSharpCodeCompletionContext, ValidatableViewModelValidateCodeCompletion.Data>
    {
        #region Nested types

        public sealed class Data
        {
            public ICSharpLiteralExpression LiteralExpression { get; set; }

            public IEnumerable<IProperty> Properties { get; set; }
        }

        #endregion

        #region Overrides of ItemsProviderOfSpecificContextWithSharedData<CSharpCodeCompletionContext,Data>

        protected override bool AddLookupItems(CSharpCodeCompletionContext context, GroupedItemsCollector collector,
            Data data)
        {
            TreeTextRange contentTreeRange = data.LiteralExpression.GetStringLiteralContentTreeRange();
            TextRange textRange = context.BasicContext.File.GetDocumentRange(contentTreeRange).TextRange;
            var ranges = new TextLookupRanges(textRange, textRange);
            IRangeMarker mappingToDocument = ranges
                .ReplaceRange
                .CreateRangeMarkerWithMappingToDocument(context.BasicContext.Document);

            foreach (var group in data.Properties.GroupBy(property => property.ShortName))
            {
                IProperty property = @group.First();
                ITextualLookupItem item = context
                    .LookupItemsFactory
                    .CreateDeclaredElementLookupItem(property.ShortName, property);
                item.VisualReplaceRangeMarker = mappingToDocument;
                item.InitializeRanges(ranges, context.BasicContext);
                collector.AddAtDefaultPlace(item);
            }
            return true;
        }

        protected override Data IsAvailable(CSharpCodeCompletionContext context)
        {
            var node = TextControlToPsi
                .GetElement<ITreeNode>(context.BasicContext.Solution, context.BasicContext.TextControl);
            var result = ToolkitExtensions
                .TryGetValidateMethod(node == null ? null : node.Parent as ICSharpLiteralExpression, context.PsiModule, context.BasicContext.SourceFile.ResolveContext);
            if (result == null)
                return null;
            return new Data
            {
                LiteralExpression = result.Item1,
                Properties = result.Item3
            };
        }

        #endregion
    }
}